/**
 * 静态资源中间件
 * 为上传的文件提供优化的跨域和缓存策略
 */

import path from 'path';
import fs from 'fs';

/**
 * 静态资源CORS和缓存中间件
 */
export const staticAssetsCors = (req, res, next) => {
  // 设置CORS头部 - 允许所有域名访问静态资源
  res.set({
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
    'Access-Control-Allow-Headers': 'Range, Content-Type, If-Range, If-Modified-Since, If-None-Match',
    'Access-Control-Expose-Headers': 'Content-Length, Content-Range, Accept-Ranges, ETag, Last-Modified'
  });

  // 处理预检请求
  if (req.method === 'OPTIONS') {
    res.status(200).end();
    return;
  }

  // 设置缓存策略
  const isImage = /\.(jpg|jpeg|png|gif|webp|svg|ico)$/i.test(req.path);
  const isDocument = /\.(pdf|doc|docx|txt)$/i.test(req.path);
  
  if (isImage) {
    // 图片文件：长期缓存
    res.set({
      'Cache-Control': 'public, max-age=31536000, immutable', // 1年缓存，不可变
      'Expires': new Date(Date.now() + 31536000000).toUTCString()
    });
  } else if (isDocument) {
    // 文档文件：中期缓存
    res.set({
      'Cache-Control': 'public, max-age=86400', // 1天缓存
      'Expires': new Date(Date.now() + 86400000).toUTCString()
    });
  } else {
    // 其他文件：短期缓存
    res.set({
      'Cache-Control': 'public, max-age=3600', // 1小时缓存
      'Expires': new Date(Date.now() + 3600000).toUTCString()
    });
  }

  next();
};

/**
 * 文件安全检查中间件
 */
export const fileSecurityCheck = (req, res, next) => {
  const filePath = req.path;
  
  // 检查文件路径安全性
  if (filePath.includes('..') || filePath.includes('~')) {
    return res.status(403).json({
      code: 403,
      message: '禁止访问'
    });
  }

  // 检查文件扩展名
  const allowedExtensions = [
    '.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.ico', // 图片
    '.pdf', '.doc', '.docx', '.txt', '.md', // 文档
    '.mp4', '.avi', '.mov', '.wmv', // 视频（如果需要）
    '.mp3', '.wav', '.ogg' // 音频（如果需要）
  ];

  const ext = path.extname(filePath).toLowerCase();
  if (ext && !allowedExtensions.includes(ext)) {
    return res.status(403).json({
      code: 403,
      message: '不支持的文件类型'
    });
  }

  next();
};

/**
 * 文件存在性检查中间件
 */
export const fileExistsCheck = (uploadDir) => {
  return (req, res, next) => {
    const filePath = path.join(uploadDir, req.path);
    
    // 检查文件是否存在
    fs.access(filePath, fs.constants.F_OK, (err) => {
      if (err) {
        return res.status(404).json({
          code: 404,
          message: '文件不存在'
        });
      }
      next();
    });
  };
};

/**
 * Range请求支持中间件
 */
export const rangeRequestSupport = (uploadDir) => {
  return (req, res, next) => {
    const range = req.headers.range;
    
    if (!range) {
      return next();
    }

    const filePath = path.join(uploadDir, req.path);
    
    fs.stat(filePath, (err, stats) => {
      if (err) {
        return next();
      }

      const fileSize = stats.size;
      const parts = range.replace(/bytes=/, "").split("-");
      const start = parseInt(parts[0], 10);
      const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
      const chunksize = (end - start) + 1;

      if (start >= fileSize || end >= fileSize) {
        res.status(416).set({
          'Content-Range': `bytes */${fileSize}`
        });
        return res.end();
      }

      res.status(206).set({
        'Content-Range': `bytes ${start}-${end}/${fileSize}`,
        'Accept-Ranges': 'bytes',
        'Content-Length': chunksize,
        'Content-Type': 'application/octet-stream'
      });

      const stream = fs.createReadStream(filePath, { start, end });
      stream.pipe(res);
    });
  };
};

/**
 * 组合中间件 - 完整的静态资源处理
 */
export const createStaticAssetsMiddleware = (uploadDir) => {
  return [
    staticAssetsCors,
    fileSecurityCheck,
    fileExistsCheck(uploadDir),
    rangeRequestSupport(uploadDir)
  ];
};

/**
 * 获取文件MIME类型
 */
export const getMimeType = (filePath) => {
  const ext = path.extname(filePath).toLowerCase();
  const mimeTypes = {
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.png': 'image/png',
    '.gif': 'image/gif',
    '.webp': 'image/webp',
    '.svg': 'image/svg+xml',
    '.ico': 'image/x-icon',
    '.pdf': 'application/pdf',
    '.doc': 'application/msword',
    '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    '.txt': 'text/plain',
    '.md': 'text/markdown',
    '.mp4': 'video/mp4',
    '.avi': 'video/x-msvideo',
    '.mov': 'video/quicktime',
    '.wmv': 'video/x-ms-wmv',
    '.mp3': 'audio/mpeg',
    '.wav': 'audio/wav',
    '.ogg': 'audio/ogg'
  };

  return mimeTypes[ext] || 'application/octet-stream';
};

/**
 * 设置正确的Content-Type中间件
 */
export const setContentType = (req, res, next) => {
  const mimeType = getMimeType(req.path);
  res.set('Content-Type', mimeType);
  next();
};
